﻿using Prism.DryIoc;
using Prism.Events;
using Prism.Ioc;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using WaferSelectV3.Common;
using WaferSelectV3.Dialogs;
using WaferSelectV3.Services;
using WaferSelectV3.ViewModels;
using WaferSelectV3.ViewModels.DialogViewModels;
using WaferSelectV3.ViewModels.SetParamsViewModels;
using WaferSelectV3.Views;
using WaferSelectV3.Views.SetParamsPages;

namespace WaferSelectV3
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication
    {
        public App()
        {
            LoggerHelper.WriteLogMain("程序启动...", LogType.Info);
            // 程序启动入口事件
            Startup += Application_Startup;
            // UI线程未捕获异常事件
            DispatcherUnhandledException += App_DispatcherUnhandledException;
            // 异步Task任务中未捕获异常
            TaskScheduler.UnobservedTaskException += Task_UnObservedTaskException;
            // 整个程序域未捕获异常
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        }

        protected override void OnInitialized()
        {
            base.OnInitialized();
            // 1. 模拟一个UI异常
            //RaiseUiException();
            // 2. 配置导航视图
            RegisterViewForRegion();
        }

        /// <summary>
        /// 配置导航关联的视图,主界面上的导航视图不需要显示的关联.但是弹窗的配置页面的导航视图
        /// 需要在这里手动的注册,不然找不到对应的区域.
        /// </summary>
        private void RegisterViewForRegion()
        {
            var regionManager = Container.Resolve<IRegionManager>();
            regionManager.Regions.Add(RegionNameManager.SetParamsContent, new Region());
            regionManager.RegisterViewWithRegion(RegionNameManager.SetParamsContent, nameof(SlaveSettingsView));
        }


        // 模拟一个UI异常,测试的时候使用
        private void RaiseUiException()
        {
            try
            {
                throw new ArgumentOutOfRangeException("内部异常");
            }
            catch (Exception ex)
            {
                ex.Data.Add("DatabaseName", "数据库Fioman");
                ex.Data.Add("HappenTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                ex.HelpLink = "Https//www.baidu.com";
                throw new InvalidOperationException("外部异常,这是一个模拟的外部异常,这是一个模拟的外部异常,它内部还包含了一个内部异常," +
                    "我只是用来测试显示用的,外部异常,这是一个模拟的外部异常,这是一个模拟的外部异常,它内部还包含了一个内部异常,我只是用来测试显示用的", ex);
            }
        }

        // UI线程(主线程)发生未捕获异常触发事件,当有UI未捕获的异常发生时,会调用这个方法
        private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            LoggerHelper.WriteLogCrashes("UI未捕获异常事件中: " + e.Exception.Message, LogType.Exception);
            DialogParameters parameters = new DialogParameters()
            {
                {"Title","UI未捕获异常提示" },
                {"Exception",e.Exception }
            };
            e.Handled = true;
            DialogProvider.ShowDialog(nameof(ExceptionDialog), parameters);
        }

        // 异步任务上未处理异常
        private void Task_UnObservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
        {

        }

        // 非UI线程未捕获异常处理
        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {

        }



        // 程序启动入口
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            // 1. 检测程序是否已经启动,如果已经启动就通知旧程序激活
            SingleInstanceManager.SingleInstanceCheck();
            // 2. 显示启动画面
            ShowSplashScreen();
            // 3. GC垃圾回收,优化WPF内存占用过大问题
            WpfHelper wpfHelper = new WpfHelper();
            wpfHelper.GcTaskStart(500);
        }

        private void ShowSplashScreen()
        {
            var splashScreen = new SplashScreen(@"Assets/Images/startFlash.jpg");
            splashScreen.Show(true);
        }

        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            //1. 视图导航注册,这行代码的意义,如果MainWindow中有区域,这个区域会被注册到Regions中去
            containerRegistry.RegisterForNavigation<MainWindow, MainWindowViewModel>();
            containerRegistry.RegisterSingleton<IndexViewModel>();
            containerRegistry.RegisterForNavigation<IndexView, IndexViewModel>();
            containerRegistry.RegisterForNavigation<RecipeSettingView, RecipeSettingViewModel>();
            containerRegistry.RegisterForNavigation<ResultSummaryView, ResultSummaryViewModel>();
            containerRegistry.RegisterForNavigation<SlaveControlView, IndexViewModel>();
            containerRegistry.RegisterForNavigation<AlarmLogView, AlarmLogViewModel>();
            containerRegistry.RegisterForNavigation<VisionOffsetView, VisionOffsetViewModel>();
            containerRegistry.RegisterForNavigation<HistoryQueryView, HistoryQueryViewModel>();
            containerRegistry.RegisterForNavigation<UserManagementView, UserManagementViewModel>();
            containerRegistry.RegisterForNavigation<SlaveSettingsView, SlaveSettingsViewModel>();

            // 2. 对话框视图和视图模型注册
            containerRegistry.RegisterDialog<ExceptionDialog, ExceptionDialogViewModel>();
            containerRegistry.RegisterDialog<ExceptionDetailDialog, ExceptionDetailDialogViewModel>();
            containerRegistry.RegisterDialog<InputNextCrystalDialog, InputNextCrystalViewModel>();
            containerRegistry.RegisterDialog<AddUserDialog, AddUserDialogModel>();
            containerRegistry.RegisterDialog<EditeUserDialog, EditeUserDialogModel>();

            // 这里SetParametersDialog里面也有区域,但是并没有注册到Regions中去,要手动去注册
            containerRegistry.RegisterDialog<SetParametersDialog, SetParametersViewModel>();
            containerRegistry.RegisterDialog<DataInitProcessBar, DataInitProcessBarViewModel>();


            // 3. 静态类中没有有参构造,依赖注入的对象通过静态函数去设置
            DialogProvider.SetDialogService(Container.Resolve<IDialogService>());
            AppCloseProvider.SetEventAggregator(Container.Resolve<IEventAggregator>());

        }
    }
}
